package org.xiaoyu.rpc.loadbalance;

import org.xiaoyu.rpc.Loadbalancer;
import org.xiaoyu.rpc.common.url.URL;
import org.xiaoyu.rpc.remoting.packet.Invocation;

import java.util.List;
import java.util.Random;

/**
 * Created By Have
 * 2021/7/14 17:18
 */
public class WeightLoadbalancer implements Loadbalancer {
    private ThreadLocal<Random> threadLocalRandom = ThreadLocal.withInitial(() -> {
        Random random = new Random();
        return random;
    });

    @Override
    public URL loadBalance(List<URL> urls, Invocation invocation) {
        if (threadLocalRandom.get() == null) {
            threadLocalRandom.set(new Random());
        }

        int length = urls.size();
        int[] weights = new int[length];
        int totalWeight = 0;
        boolean sameWeight = true;
        for (int i = 0; i < urls.size(); i++) {
            float weight = urls.get(0).getWeight() == null? 1.0f : urls.get(0).getWeight();
            totalWeight += weight;
            weights[i] = totalWeight;
            if (sameWeight && totalWeight != (i + 1) * weights[i]) {
                sameWeight = false;
            }
        }

        if (totalWeight > 0 && !sameWeight) {
            int offset = threadLocalRandom.get().nextInt(totalWeight);
            for (int i = 0; i < weights.length; i++) {
                if (offset < weights[i]) {
                    threadLocalRandom.remove();
                    return urls.get(i);
                }
            }
        }
        URL url = urls.get(threadLocalRandom.get().nextInt(urls.size()));
        threadLocalRandom.remove();
        return url;
    }
}
